﻿#pragma once

#include <functional>
#include <list>
#include <vector>
#include <memory>
#include <ostream>
#include <string>
#include <ctime>

namespace kratos {
namespace service {

using ServiceChange = std::function<void(const std::string& name, const std::vector<std::string>&)>;

// 服务发现接口
class ServiceFinder {
public:
  virtual ~ServiceFinder() {}
  // 启动并连接服务器
  // @param servers 多个服务地址, 例如:"127.0.0.1:2011,127.0.0.1:2012"
  // @param timeout 连接超时时间（毫秒）
  // @retval true 成功
  // @retval false 失败
  virtual auto start(const std::string &servers, int timeout) -> bool = 0;
  // 关闭服务器连接
  virtual auto stop() -> void = 0;
  // 主循环
  // @param tick 当前时间戳，毫秒
  virtual void update(std::time_t tick) = 0;
  // 发现服务
  // @param name 服务名
  // @param [OUT] 返回可用的多个服务列表
  // @retval true 成功
  // @retval false 失败
  virtual auto find_service(const std::string &name,
                            std::list<std::string> &hosts) -> bool = 0;
  // 根据负载均衡的策略发现服务
  // @param name 服务名
  // @param [OUT] 返回可用服务
  // @retval true 成功
  // @retval false 失败
  virtual auto find_service(const std::string &name, std::string &host)
      -> bool = 0;
  // 输出调试信息
  virtual auto dump(std::ostream &ostream) -> void = 0;
  // 强制从缓存内删除指定的服务
  // @param name 服务器名
  // @param host 服务地址
  virtual auto remove_cache(const std::string &name, const std::string &host)
      -> void = 0;
  /**
   * 获取服务对应的主机数量.
   * 
   * \param name 服务名
   * \return 主机数量
   */
  virtual auto get_service_host_count(const std::string& name) -> std::size_t = 0;
  /**
   * 添加服务变化监听器
   * \param listener_name 监听器名字
   * \param service_change 回调函数
   */
  virtual auto add_listener(const std::string& listener_name,
      ServiceChange service_change)->bool = 0;
};

// 根据服务器类型获取服务器发现实现
// @param type 服务器类型，支持:"zookeeper"
// @return 服务器发现实例
extern std::shared_ptr<ServiceFinder> getFinder(const std::string &type);

} // namespace service
} // namespace kratos
